use app::*;
use axum::{Router, debug_handler, routing};
use leptos::prelude::*;
use leptos_axum::{LeptosRoutes, generate_route_list};

mod config;
mod logger;
mod database;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 初始化日志记录
    logger::init();

    // 获取配置
    let _config = config::get();

    // 初始化数据库连接
    let db = database::init().await?;

    // 初始化 REST API 路由
    let api_rooter =Router::new().route("/", routing::get(health)) ;

    // 初始化 Leptos 应用路由
    let conf = get_configuration(None)?;
    let addr = conf.leptos_options.site_addr;
    let leptos_options = conf.leptos_options;
    // 生成 Leptos 应用中的路由列表
    let routes = generate_route_list(App);

    // 初始化 Leptos 应用路由
    let app = Router::new()
        .leptos_routes_with_context(
            &leptos_options, 
            routes, 
            // 提供数据库连接上下文
            move || provide_context(db.clone()),
            {
            let leptos_options = leptos_options.clone();
            move || shell(leptos_options.clone())
        }
    )
        .fallback(leptos_axum::file_and_error_handler(shell))
        .with_state(leptos_options);
    
    // 合并 REST API 路由和 Leptos 应用路由
    let app = app.nest("/rest/api", api_rooter);

    // 使用 hyper 运行应用
    // `axum::Server` 是 `hyper::Server` 的再导出
    tracing::info!("listening on http://{}", &addr);
    let listener = tokio::net::TcpListener::bind(&addr).await?;
    axum::serve(listener, app.into_make_service())
        .await?;
    Ok(())
}

#[debug_handler]
async fn health() -> &'static str {
    "Ok"
}